package com.yh.base.util;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

/**
 * xml处理工具，依赖dom4j组件
 */
public class XMLUtil {

    private final static Logger logger = Logger.getLogger(XMLUtil.class);

	/**
	 * 在类路径中对没有使用了DTD的XML进行加载
	 * 
	 * @param classpath
	 *            - 类路径
	 */
	public static Document getDocumentWithClassPath(String classpath) {
		SAXReader reader = new SAXReader();
		Document doc = null;
		try {
			doc = reader.read(XMLUtil.class.getClassLoader().getResourceAsStream(classpath));
		} catch (DocumentException e) {
			logger.error(e);
		}

		return doc;
	}

	/**
	 * 在文件路径中对使用了DTD的XML进行加载
	 * 
	 * @param filepath
	 *            - 文件路径
	 */
	public static Document getDocumentWithFilePath(String filepath) {
		SAXReader reader = new SAXReader();
		Document doc = null;
		try {
			doc = reader.read(new FileInputStream(filepath));
		} catch (DocumentException e) {
			logger.error(e);
		} catch (FileNotFoundException e) {
			logger.error(e);
		}

		return doc;
	}

	/**
	 * 在文件路径中对使用了DTD的XML进行加载
	 * 
	 * @param filepath
	 *            - 文件路径
	 */
	public static Document getDocumentWithString(String xmlStr) {
		if (xmlStr == null) {
			return null;
		}

		Document document = null;
		try {
			document = DocumentHelper.parseText(xmlStr);
		} catch (Exception e) {
			logger.error("getDocumentWithString----xmlStr convert error", e);
			return null;
		}
		return document;
	}

	@SuppressWarnings("rawtypes")
    public static Map<String, Object> dom2Map(Document doc) {
		Map<String, Object> map = new HashMap<String, Object>();
		if (doc == null)
			return map;
		Element root = doc.getRootElement();
		for (Iterator iterator = root.elementIterator(); iterator.hasNext();) {
			Element e = (Element) iterator.next();
			List list = e.elements();
			if (list.size() > 0) {
				map.put(e.getName(), dom2Map(e));
			} else
				map.put(e.getName(), e.getText());
		}
		return map;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
    public static Map dom2Map(Element e) {
		Map map = new HashMap();
		List list = e.elements();
		if (list.size() > 0) {
			for (int i = 0; i < list.size(); i++) {
				Element iter = (Element) list.get(i);
				List mapList = new ArrayList();

				if (iter.elements().size() > 0) {
					Map m = dom2Map(iter);
					if (map.get(iter.getName()) != null) {
						Object obj = map.get(iter.getName());
						if (!obj.getClass().getName().equals("java.util.ArrayList")) {
							mapList = new ArrayList();
							mapList.add(obj);
							mapList.add(m);
						}
						if (obj.getClass().getName().equals("java.util.ArrayList")) {
							mapList = (List) obj;
							mapList.add(m);
						}
						map.put(iter.getName(), mapList);
					} else
						map.put(iter.getName(), m);
				} else {
					if (map.get(iter.getName()) != null) {
						Object obj = map.get(iter.getName());
						if (!obj.getClass().getName().equals("java.util.ArrayList")) {
							mapList = new ArrayList();
							mapList.add(obj);
							mapList.add(iter.getText());
						}
						if (obj.getClass().getName().equals("java.util.ArrayList")) {
							mapList = (List) obj;
							mapList.add(iter.getText());
						}
						map.put(iter.getName(), mapList);
					} else
						map.put(iter.getName(), iter.getText());
				}
			}
		} else
			map.put(e.getName(), e.getText());
		return map;
	}

	// XML格式符号
	@SuppressWarnings("unused")
    private static final String XML_START_LEFT = "<";
	@SuppressWarnings("unused")
	private static final String XML_RIGHT = ">";
	@SuppressWarnings("unused")
	private static final String XML_END_LEFT = "</";
	@SuppressWarnings("unused")
	private static final int XML_INIT_LENGTH = 1000;

	/**
	 * 
	 * @Title: listMapToXML
	 * @param @param list
	 * @param @param entityName
	 * @param @return
	 * @return String
	 * @throws
	 */
	public static String mapToXML(Map<String, Object> map) {
		if (map == null) {
			// throw new SysLevelException("将MAP转换为XML出错！map=null");
			map = new HashMap<String, Object>();
		}
		StringBuffer xml = new StringBuffer();
		xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
		Object rootName = map.get("ROOT_NAME");
		if (rootName == null) {
			rootName = "LIST";
		}
		xml.append(parseMapToXML(map, rootName.toString()));
		System.out.println(xml.toString());
		return xml.toString();
	}

	/**
	 * 
	 * @Title: parseListMapToXML
	 * @param @param list
	 * @param @param entityName
	 * @param @return
	 * @return String
	 * @throws
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
    private static String parseListMapToXML(List list, String entityName) {
		StringBuffer xml = new StringBuffer();
		xml.append("<" + entityName + " type=\"list\">\n");
		for (Object obj : list) {
			String centityName = entityName.substring(0, entityName.length() - 1);
			if (obj instanceof String || obj instanceof Timestamp || obj instanceof Integer || obj instanceof BigDecimal) {

			} else if (obj instanceof Map) {
				xml.append(parseMapToXML((Map<String, Object>) obj, centityName));
			} else if (obj instanceof List) {
				xml.append(parseListMapToXML((List<Object>) obj, centityName));
			}
		}
		xml.append("</" + entityName + ">\n");
		return xml.toString();
	}

	/**
	 * 
	 * @Title: parseMapToXML
	 * @param @param map
	 * @param @param entityName
	 * @param @return
	 * @return String
	 * @throws
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	private static String parseMapToXML(Map<String, Object> map, String entityName) {
		StringBuffer xml = new StringBuffer();
		Set<Map.Entry<String, Object>> set = map.entrySet();
		// 所有Map
		Map maps = new HashMap();
		// 所有List
		Map list = new HashMap();
		xml.append("<" + entityName + " type=\"map\">\n");
		for (Iterator<Map.Entry<String, Object>> it = set.iterator(); it.hasNext();) {
			Map.Entry<String, Object> entry = (Map.Entry<String, Object>) it.next();
			// if(entry.getKey().equals("LICENSE_KEY")){
			// xml.append("<LICENSE_KEY value=\""+entry.getValue()+"\"/>\n");
			// }else if(entry.getKey().equals("RESPONSE_CODE")){
			// xml.append("<RESPONSE_CODE value=\""+entry.getValue()+"\"/>\n");
			// }else
			if (entry.getValue() instanceof String || entry.getValue() instanceof Timestamp || entry.getValue() instanceof Integer || entry.getValue() instanceof BigDecimal) {
				xml.append("<" + entry.getKey() + " value=\"" + entry.getValue() + "\"/>\n");
			} else if (entry.getValue() == null) {
				xml.append("<" + entry.getKey() + " value=\"\"/>\n");
			} else if (entry.getValue() instanceof List) {
				List listValue = (List) entry.getValue();
				list.put(entry.getKey(), listValue);
			} else if (entry.getValue() instanceof Map) {
				maps.put(entry.getKey(), (Map<String, Object>) entry.getValue());
			} else {
				System.out.println(entry.getKey() + "------------------" + entry.getValue());
			}
		}
		Set<Entry<String, Map<String, Object>>> set1 = maps.entrySet();
		for (Iterator<Entry<String, Map<String, Object>>> it = set1.iterator(); it.hasNext();) {
			Map.Entry<String, Map<String, Object>> entry = (Map.Entry<String, Map<String, Object>>) it.next();
			xml.append(parseMapToXML(entry.getValue(), entry.getKey()));
		}
		Set<Entry<String, List<Map<String, Object>>>> set2 = list.entrySet();
		for (Iterator<Entry<String, List<Map<String, Object>>>> it = set2.iterator(); it.hasNext();) {
			Map.Entry<String, List<Map<String, Object>>> entry = (Map.Entry<String, List<Map<String, Object>>>) it.next();
			List listValue = (List) entry.getValue();
			listValue.add(0, entry.getKey());

			Map<String, Object> lm = new HashMap<String, Object>();
			lm.put(entry.getKey(), entry.getValue());
			xml.append(parseListMapToXML(entry.getValue(), entry.getKey()));
		}
		xml.append("</" + entityName + ">\n");
		return xml.toString();
	}
}
